﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace PMS
{
    public class Audit
    {
        /// <summary>
        /// 新增审批
        /// </summary>
        /// <param name="type"></param>
        /// <param name="money"></param>
        /// <returns></returns>
        public static int AddAudit(string type, float money)
        {
            BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == type).FirstOrDefault();
            int totalId = 0;
            if (doc != null)
            {
                List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
                List<BD_LedRevInfo> highList = DALSession.Current.BD_LedRevInfoDAL.GetListBy(l => l.DocId == doc.ID).ToList();
                BD_ReviewTotal total = new BD_ReviewTotal() { DocId = doc.ID, DocCode = doc.DocCode, FillDate = DateTime.Now.ToString("yyyy-MM-dd"), AddPerson = OperateContext.sessUserInfo.Name, AddPersonId = OperateContext.sessUserInfo.Id, RevTable = doc.RevTable, TotalState = "0", RevFolw = doc.RevFolw, IsInform = "0", ModName = doc.ModName, DocName = doc.DocName, TotalUrl = doc.TotalUrl };
                var lastTotal = DALSession.Current.BD_ReviewTotalDAL.GetListBy(r => r.DocCode == type, o => o.RevNum, false).FirstOrDefault();
                if (lastTotal == null)
                {
                    total.RevNum = doc.OrderName + DateTime.Now.Year.ToString() + "000001";
                }
                else
                {
                    int num = Commons.String2Int32(lastTotal.RevNum.Substring(lastTotal.RevNum.Length - 6, 6)) + 1;
                    total.RevNum = doc.OrderName + DateTime.Now.Year.ToString() + num.ToString().PadLeft(6, '0');
                }
                totalId = Commons.String2Int32(DALSession.Current.BD_ReviewTotalDAL.AddModelReturnId(total, "ID"));
                foreach (var item in lowList)
                {
                    BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalId, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                    DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                }
                foreach (var high in highList)
                {
                    if (high.MoneyMax >= money && high.MoneyMin <= money)
                    {
                        BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalId, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                    }
                }
            }
            return totalId;
        }
        //询比价专用审批方法
        public static int AddAuditComprice(string type, float money, string HtYs)
        {
            BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == type).FirstOrDefault();
            int totalId = 0;
            if (doc != null)
            {
                List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
                List<BD_LedRevInfo> highList = DALSession.Current.BD_LedRevInfoDAL.GetListBy(l => l.DocId == doc.ID).ToList();

                BD_ReviewTotal total = new BD_ReviewTotal() { DocId = doc.ID, DocCode = doc.DocCode, FillDate = DateTime.Now.ToString("yyyy-MM-dd"), AddPerson = OperateContext.sessUserInfo.Name, AddPersonId = OperateContext.sessUserInfo.Id, RevTable = doc.RevTable, TotalState = "0", RevFolw = doc.RevFolw, IsInform = "0", ModName = doc.ModName, DocName = doc.DocName, TotalUrl = doc.TotalUrl };
                var lastTotal = DALSession.Current.BD_ReviewTotalDAL.GetListBy(r => r.DocCode == type, o => o.RevNum, false).FirstOrDefault();
                if (lastTotal == null)
                {
                    total.RevNum = doc.OrderName + "000001";
                }
                else
                {
                    int num = Commons.String2Int32(lastTotal.RevNum.Substring(lastTotal.RevNum.Length - 6, 6)) + 1;
                    total.RevNum = doc.OrderName + num.ToString().PadLeft(6, '0');
                }
                totalId = Commons.String2Int32(DALSession.Current.BD_ReviewTotalDAL.AddModelReturnId(total, "ID"));

                foreach (var item in lowList)
                {

                    BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalId, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                    DALSession.Current.BD_ReviewDetailDAL.Add(detail);


                }
                foreach (var high in highList)
                {
                    if (high.MoneyMax >= money && high.MoneyMin <= money)
                    {


                        BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalId, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail);


                    }
                    if (type == "0301" && HtYs == "1" && high.RankName == "财务部")//比价单参与了预算
                    {
                        BD_ReviewDetail detail2 = new BD_ReviewDetail() { ReviewerId = totalId, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail2);
                    }

                }

            }
            return totalId;
        }




        /// <summary>
        /// 重新刷新审批明细
        /// </summary>
        /// <param name="type"></param>
        /// <param name="money"></param>
        /// <returns></returns>
        public static void ResetAuditDetail(int reviewId, float money)
        {

            var total = DALSession.Current.BD_ReviewTotalDAL.GetListBy(r => r.ID == reviewId).FirstOrDefault();
            DALSession.Current.BD_ReviewDetailDAL.DelBy(d => d.ReviewerId == total.ID);
            if (total != null)
            {
                BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == total.DocCode).FirstOrDefault();

                List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
                List<BD_LedRevInfo> highList = DALSession.Current.BD_LedRevInfoDAL.GetListBy(l => l.DocId == doc.ID).ToList();

                foreach (var item in lowList)
                {
                    BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = total.ID, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                    DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                }
                foreach (var high in highList)
                {
                    if (high.MoneyMax >= money && high.MoneyMin <= money)
                    {
                        BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = total.ID, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                    }

                }
                DALSession.Current.Savechanges();
            }
        }
        //比价单审批专用
        public static void ResetAuditDetailComprice(int reviewId, float money, string HtYs)
        {

            var total = DALSession.Current.BD_ReviewTotalDAL.GetListBy(r => r.ID == reviewId).FirstOrDefault();
            DALSession.Current.BD_ReviewDetailDAL.DelBy(d => d.ReviewerId == total.ID);
            if (total != null)
            {
                BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == total.DocCode).FirstOrDefault();

                List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
                List<BD_LedRevInfo> highList = DALSession.Current.BD_LedRevInfoDAL.GetListBy(l => l.DocId == doc.ID).ToList();

                foreach (var item in lowList)
                {
                    BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = total.ID, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                    DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                }
                foreach (var high in highList)
                {
                    if (high.MoneyMax >= money && high.MoneyMin <= money)
                    {
                        BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = total.ID, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                    }
                    if (HtYs == "1" && high.RankName == "财务部")//比价单参与了预算
                    {
                        BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = total.ID, RevState = "0", IsLeadOrDep = "1", RankName = high.RankName, Rank = high.Rank, RevGroup = high.RevGroup, CanDelete = "0", DocNum = high.ID };
                        DALSession.Current.BD_ReviewDetailDAL.Add(detail);
                    }

                }
                DALSession.Current.Savechanges();
            }
        }







        public static void BeginAudit(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev, List<View_BD_UserDepInfo> userList)
        {
            BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.ID == totalRev.DocId).FirstOrDefault();
            string currentAudit = "";
            string currentReviewName = "";
            if (detailRev.Count == 0)
            {
                totalRev.TotalState = "1";
                if (!string.IsNullOrEmpty(doc.SuccessMethod))
                {
                    GoMethod(totalRev, detailRev, doc, "Success");
                }
            }
            else
            {
                totalRev.TotalState = "3";
                currentAudit = ",";
                var first = detailRev.OrderBy(o => o.IsLeadOrDep).ThenBy(o => o.RevGroup).FirstOrDefault();
                detailRev.ForEach(d =>
                {
                    if (d.RevState == "0" && d.IsLeadOrDep == first.IsLeadOrDep && d.RevGroup == first.RevGroup)
                    {
                        currentAudit += d.Reviewer + ",";
                        currentReviewName += userList.Where(u => u.ID == d.Reviewer).FirstOrDefault().UserName + ",";
                    }
                });
                totalRev.CurrentReviewer = currentAudit;
                totalRev.CurrentReviewName = currentReviewName.Trim(',');
                if (!string.IsNullOrEmpty(doc.BegionMethod))
                {
                    GoMethod(totalRev, detailRev, doc, "Begion");
                }
                foreach (var item in detailRev)
                {
                    DALSession.Current.BD_ReviewDetailDAL.ModifyAllModel(item);
                }
            }
            DALSession.Current.BD_ReviewTotalDAL.ModifyAllModel(totalRev);
            DALSession.Current.Savechanges();
        }
        /// <summary>
        /// 根据当前审批人的审批结果，流转审批
        /// </summary>
        /// <param name="revResult">当前审批结果类</param>
        /// <param name="totalRev">审批总表</param>
        /// <param name="detailRev">审批分表</param>
        public static Message SubmitAudit(ReviewResult revResult, BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev, List<View_BD_UserDepInfo> userList)
        {
            Message msg = new Message() { state = "success", msg = "提交成功，审批流程将跳转到下一级！" };
            BD_ReviewDetail currentRow = detailRev.Where(d => d.Reviewer == revResult.RevPeoId && d.RevState == "0").OrderBy(d => d.IsLeadOrDep).ThenBy(d => d.RevGroup).FirstOrDefault();
            if (currentRow != null)
            {
                currentRow.RevState = revResult.RevResult;
                currentRow.RevAdv = revResult.RevAdv;
                currentRow.RevTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                //如果审核模式为驳回终止，并且审核结果为驳回，则该流程终止，总状态为驳回状态，否则流程继续
                if (totalRev.RevFolw == "1" && currentRow.RevState == "2")
                {
                    totalRev.CurrentReviewer = "";
                    totalRev.CurrentReviewName = "";
                    totalRev.FinishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    totalRev.TotalState = "2";
                }
                else
                {
                    //判断审核是否全部完成，如果完成，则审核结果为最后一个审批人的结果
                    if (CheckAuditIsComplete(detailRev))
                    {
                        totalRev.CurrentReviewer = "";
                        totalRev.CurrentReviewName = "";
                        totalRev.TotalState = currentRow.RevState;
                        totalRev.FinishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                    else
                    {
                        //当前审核人
                        UpdateCurrentAudit(totalRev, detailRev, userList);
                    }
                }
                DALSession.Current.BD_ReviewTotalDAL.ModifyAllModel(totalRev);
                foreach (var item in detailRev)
                {
                    DALSession.Current.BD_ReviewDetailDAL.ModifyAllModel(item);
                }
                DALSession.Current.Savechanges();

                BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.ID == totalRev.DocId).FirstOrDefault();
                if (doc != null)
                {
                    if (totalRev.TotalState == "1")
                    {
                        GoMethod(totalRev, detailRev, doc, "Success");

                        if (doc.PassToAdd == "0")
                        {
                            SentFinalyEmail(totalRev, detailRev, revResult.RevPeoName, doc);
                        }

                    }
                    else if (totalRev.TotalState == "2")
                    {
                        GoMethod(totalRev, detailRev, doc, "Reject");
                        if (doc.RejectToAdd == "0")
                        {
                            SentFinalyEmail(totalRev, detailRev, revResult.RevPeoName, doc);
                        }
                    }

                }
            }
            else
            {
                msg.state = "error";
                msg.msg = "您无权审核当前任务，请重新登录查看！";
            }
            return msg;

        }

        private static void GoMethod(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev, BD_RevDocInfo doc, string type)
        {
            if (!string.IsNullOrEmpty(doc.Class))
            {
                Type auditClass = Type.GetType("PMS.AuditClass." + doc.Class.Trim());
                string method = "";
                switch (type)
                {
                    case "Begion":
                        method = doc.BegionMethod;
                        break;
                    case "Success":
                        method = doc.SuccessMethod;
                        break;
                    case "Reject":
                        method = doc.RejectMethod;
                        break;
                    case "ReSubmit":
                        method = doc.ReSubmitMethod;
                        break;
                    case "Back":
                        method = doc.BackAuditMethod;
                        break;
                    default:
                        break;
                }
                if (!string.IsNullOrEmpty(method))
                {
                    MethodInfo mf = auditClass.GetMethod(method.Trim(), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(BD_ReviewTotal), typeof(List<BD_ReviewDetail>) }, null);
                    mf.Invoke(null, new object[] { totalRev, detailRev });
                }
            }
        }
        /// <summary>
        /// 最终根据单据是否审批成功，或者驳回，通知制单人或审批人，或需要通知的人
        /// </summary>
        /// <param name="totalRev"></param>
        /// <param name="detailRev"></param>
        /// <param name="userList"></param>
        private static void SentFinalyEmail(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev, string operName, BD_RevDocInfo doc)
        {
            BD_SystemMessage message = new BD_SystemMessage()
            {
                ToId = (int)totalRev.AddPersonId,
                ToName = totalRev.AddPerson,
                Url = totalRev.TotalUrl + "?action=view&reviewId=" + totalRev.ID

            };
            if (totalRev.TotalState == "1")
            {
                //审批成功
                message.Content = "您发起的审批 " + totalRev.DocName + ":" + totalRev.RevNum + " 已经审核通过！";
                message.Title = "审批通过通知";
            }
            else if (totalRev.TotalState == "2")
            {
                message.Title = "审批驳回通知";
                message.Content = "    您发起的审批 " + totalRev.DocName + ":" + totalRev.RevNum + " 被 " + operName + " 驳回!\r";
                if (doc.CanReSubmit == "0")
                {
                    message.Content += "    请注意：该单据可以重新编辑提交！";
                }
                else
                {
                    message.Content += "    请注意：该单据无法重新编辑，请重新制单并提交！";
                }
            }
            SystemMessage.SendSystemMessage(message);
        }


        /// <summary>
        /// 根据审核明细表结果，更新当前审核人
        /// </summary>
        /// <param name="totalRev"></param>
        /// <param name="detailRev"></param>
        private static void UpdateCurrentAudit(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev, List<View_BD_UserDepInfo> userList)
        {
            List<IGrouping<string, BD_ReviewDetail>> group = detailRev.GroupBy(d => d.IsLeadOrDep.ToString() + "|" + d.RevGroup.ToString()).OrderBy(d => d.Key).ToList();
            for (int i = 0; i < group.Count(); i++)
            {
                int currentCount = group[i].Count(g => g.RevState == "0" || g.RevState == "" || g.RevState == null);
                if (currentCount != 0)
                {
                    SetCurrentGroup(totalRev, group[i], userList);
                    return;
                }
                else
                {
                    if (i < group.Count - 1)
                    {

                        int nextCount = group[i + 1].Count(g => g.RevState == "0" || g.RevState == "" || g.RevState == null);
                        if (nextCount != 0)
                        {
                            SetCurrentGroup(totalRev, group[i + 1], userList);
                            return;
                        }

                    }
                }
            }
        }

        public static void SetCurrentGroup(BD_ReviewTotal totalRev, IGrouping<string, BD_ReviewDetail> group, List<View_BD_UserDepInfo> userList)
        {
            string currentAudit = ",";
            string currentReviewName = "";
            foreach (var item in group)
            {
                if (item.RevState == "0")
                {
                    currentAudit += item.Reviewer + ",";
                    currentReviewName += userList.Where(u => u.ID == item.Reviewer).FirstOrDefault().UserName + ",";

                }
            }
            totalRev.CurrentReviewer = currentAudit;
            totalRev.CurrentReviewName = currentReviewName.Trim(',');
        }

        /// <summary>
        /// 检查审批是否完成
        /// </summary>
        /// <param name="detailRev"></param>
        private static bool CheckAuditIsComplete(List<BD_ReviewDetail> detailRev)
        {
            return detailRev.Count(d => d.RevState == "0") == 0;
        }

        public static bool BackAudit(int reviewId)
        {
            BD_ReviewTotal total = DALSession.Current.BD_ReviewTotalDAL.GetListBy(r => r.ID == reviewId).FirstOrDefault();
            List<BD_ReviewDetail> detail = DALSession.Current.BD_ReviewDetailDAL.GetListBy(r => r.ReviewerId == reviewId).ToList();
            BD_RevDocInfo rev = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.ID == total.DocId).FirstOrDefault();
            if (rev.CanBackAudit == "0")
            {
                total.TotalState = "0";
                total.CurrentReviewer = "";
                total.CurrentReviewName = "";
                detail.ForEach(d =>
                {
                    d.RevState = "0";
                    DALSession.Current.BD_ReviewDetailDAL.ModifyAllModel(d);
                });
                DALSession.Current.BD_ReviewTotalDAL.ModifyAllModel(total);


                DALSession.Current.Savechanges();
                if (!string.IsNullOrEmpty(rev.BackAuditMethod))
                {
                    try
                    {
                        Type auditClass = Type.GetType("PMS." + rev.Class);
                        MethodInfo mf = auditClass.GetMethod(rev.BackAuditMethod, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(BD_ReviewTotal), typeof(List<BD_ReviewDetail>) }, null);
                        mf.Invoke(null, new object[] { total, detail });
                        return true;
                    }
                    catch (Exception)
                    {

                        return false;
                    }

                }
                return true;
            }
            else
            {
                return false;
            }

        }

        /// <summary>
        /// 被驳回的单据重新初始化
        /// </summary>
        /// <param name="totalRev"></param>
        /// <param name="detailRev"></param>
        internal static void ResetReview(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev)
        {
            totalRev.TotalState = "0";
            foreach (var item in detailRev)
            {
                item.RevState = "0";
                item.RevTime = "";
                item.RevAdv = "";
            }

            BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == totalRev.DocCode).FirstOrDefault();
            DALSession.Current.BD_ReviewDetailDAL.DelBy(r => r.ReviewerId == totalRev.ID && r.IsLeadOrDep == "0");
            List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
            foreach (var item in lowList)
            {
                BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalRev.ID, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, ComboId = item.ComboId, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                DALSession.Current.BD_ReviewDetailDAL.Add(detail);
            }

            if (!string.IsNullOrEmpty(doc.ReSubmitMethod))
            {
                GoMethod(totalRev, detailRev, doc, "ReSubmit");
            }
            DALSession.Current.Savechanges();
        }

        internal static void BackReview(BD_ReviewTotal totalRev, List<BD_ReviewDetail> detailRev)
        {
            totalRev.TotalState = "0";
            foreach (var item in detailRev)
            {
                item.RevState = "0";
                item.RevTime = "";
                item.RevAdv = "";
                DALSession.Current.BD_ReviewDetailDAL.ModifyBy(item, r => r.ID == item.ID, "RevState", "RevTime", "RevAdv");
            }


            BD_RevDocInfo doc = DALSession.Current.BD_RevDocInfoDAL.GetListBy(r => r.DocCode == totalRev.DocCode).FirstOrDefault();
            DALSession.Current.BD_ReviewDetailDAL.DelBy(r => r.ReviewerId == totalRev.ID);
            List<BD_DepRevInfo> lowList = DALSession.Current.BD_DepRevInfoDAL.GetListBy(d => d.DocId == doc.ID).ToList();
            foreach (var item in lowList)
            {
                BD_ReviewDetail detail = new BD_ReviewDetail() { ReviewerId = totalRev.ID, RevState = "0", IsLeadOrDep = "0", RankName = item.RankName, Rank = item.Rank, RevGroup = item.RevGroup, ComboId = item.ComboId, IsAuth = "0", CanDelete = item.CanDelete, DocNum = item.ID };
                DALSession.Current.BD_ReviewDetailDAL.Add(detail);
            }


            if (!string.IsNullOrEmpty(doc.BackAuditMethod))
            {
                GoMethod(totalRev, detailRev, doc, "Back");
            }

            DALSession.Current.Savechanges();
        }
    }
}